home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / utilities / pu194.dms / pu194.adf / MouseBlanker / MouseBlanker.c < prev    next >
C/C++ Source or Header  |  1992-04-13  |  43KB  |  1,341 lines

  1. /*
  2.  *  MouseBlanker.c
  3.  *
  4.  *  Commodity
  5.  *
  6.  *  Author: Stefan Sticht
  7.  *
  8.  *  Copyright: source is public domain, no copyright
  9.  *
  10.  *  Version history:
  11.  *
  12.  *  V1.00   initial release
  13.  *  V1.03   added window
  14.  *  V1.04   recompiled with window.c V1.01
  15.  *  V1.05   recompiled with window.c V1.02
  16.  *  V1.06   recompiled with main.c V1.02
  17.  *  V1.07   completly rewritten; shared commodity code thrown away; smaller, uses less CPU time
  18.  *  V1.08   uses now Stricmp from utility.library
  19.  *  V1.09   changed parameter parsing
  20.  *  V1.10   changed parameter parsing; introduced an error with V1.09
  21.  *  V1.11   a minor change
  22.  *  V1.12   replaced menu by gadtools underscores & vanillakeys
  23.  *          added blanking on key option
  24.  *          disables inputevent-filters if not needed
  25.  *  V1.13   added some LockIBase() where needed
  26.  */
  27.  
  28. #define VERSION "V1.13"
  29.  
  30. /********************************************************************
  31.  *                             interfacing                          *
  32.  ********************************************************************/
  33.  
  34. /*
  35.  *  include files
  36.  */
  37.  
  38. #include <math.h>
  39. #include <stdarg.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <devices/inputevent.h>
  43. #include <hardware/custom.h>
  44. #include <hardware/dmabits.h>
  45. #include <graphics/gfxmacros.h>
  46. #include <intuition/intuitionbase.h>
  47. #include <libraries/commodities.h>
  48.  
  49. #include <clib/alib_protos.h>
  50. #include <clib/commodities_protos.h>
  51. #include <pragmas/commodities_pragmas.h>
  52. #include <clib/dos_protos.h>
  53. #include <pragmas/dos_pragmas.h>
  54. #include <clib/exec_protos.h>
  55. #include <pragmas/exec_pragmas.h>
  56. #include <clib/gadtools_protos.h>
  57. #include <pragmas/gadtools_pragmas.h>
  58. #include <clib/graphics_protos.h>
  59. #include <pragmas/graphics_pragmas.h>
  60. #include <clib/intuition_protos.h>
  61. #include <pragmas/intuition_pragmas.h>
  62. #include <clib/utility_protos.h>
  63. #include <pragmas/utility_pragmas.h>
  64.  
  65. #ifdef DEBUG
  66. #define printf KPrintF
  67. #include <clib/dlib_protos.h>
  68. #endif
  69.  
  70. /*
  71.  *  prototypes
  72.  */
  73. long openwindow(void);
  74. struct Gadget *
  75. createallgadgets(struct Gadget **glist, APTR vi, struct Screen *scr, ULONG *height, ULONG *width);
  76. struct Library *myopenlibrary(char *name, unsigned long version);
  77. void __saveds mousemon(void);
  78. void __saveds timermon(void);
  79. void __saveds keymon(CxMsg *cxm);
  80. void changestateofmousepointer(unsigned char blanked);
  81. void closewindow(void);
  82. void getseconds(void);
  83. void processmessages(short window);
  84.  
  85. /*
  86.  *  global data defined in other moduls
  87.  *
  88.  *  libraries opened by startup code; basepointers needed by function pragmas
  89.  */
  90. extern struct Library *DOSBase;
  91. extern struct Library *SysBase;
  92.  
  93. /*
  94.  *  access to custom chips
  95.  */
  96. extern struct Custom __far custom;
  97.  
  98. /*
  99.  *  Disable SAS/C CTRL/C handling
  100.  */
  101. void chkabort(void) {}
  102.  
  103. /********************************************************************
  104.  *                             global data                          *
  105.  ********************************************************************/
  106.  
  107. /*
  108.  *  definition of all messages (multi language support not completed yet)
  109.  */
  110. #ifdef GERMAN
  111.  
  112. #define RETRY_GADGETS           "Wiederholen|Abbrechen"
  113. #define RESUME_GADGETS          "Weiter"
  114. #define MSG_LIBRARY_OPENERR     "Die %s (V%ld+) kann nicht geöffnet werden!"
  115. #define COM_NAME                "Mausweg"
  116. #define COM_DESCR               "Versteckt Mauszeiger"
  117. #define MSG_PROJECT             "Projekt"
  118. #define MSG_SECONDS             "_Sekunden:"
  119. #define MSG_SECONDS_SCC         'S'
  120. #define MSG_KEY                 "auf _Tastendruck löschen"
  121. #define MSG_KEY_SCC             'T'
  122. #define MSG_HIDE                "_Verstecken"
  123. #define MSG_HIDE_SCC            'V'
  124. #define MSG_QUIT                "_Beenden"
  125. #define MSG_QUIT_SCC            'B'
  126. #define YES                     "JA"
  127. #define NO                      "NEIN"
  128. #define TT_TIMEOUT              "SEKUNDEN"
  129. #define TT_KEY                  "TASTENDRUCK"
  130.  
  131. #else
  132.  
  133. #define RETRY_GADGETS           "Retry|Cancel"
  134. #define RESUME_GADGETS          "Resume"
  135. #define MSG_LIBRARY_OPENERR     "%s (V%ld+) can't be opened!"
  136. #define COM_NAME                "MouseBlanker"
  137. #define COM_DESCR               "Blanks mouse pointer"
  138. #define MSG_PROJECT             "Project"
  139. #define MSG_SECONDS             "_Seconds:"
  140. #define MSG_SECONDS_SCC         'S'
  141. #define MSG_KEY                 "blank on pressing any _key"
  142. #define MSG_KEY_SCC             'K'
  143. #define MSG_HIDE                "_Hide"
  144. #define MSG_HIDE_SCC            'H'
  145. #define MSG_QUIT                "_Quit"
  146. #define MSG_QUIT_SCC            'Q'
  147. #define YES                     "YES"
  148. #define NO                      "NO"
  149. #define TT_TIMEOUT              "SECONDS"
  150. #define TT_KEY                  "KEYPRESS"
  151.  
  152. #endif
  153.  
  154. #define COM_TITLE           COM_NAME " " VERSION
  155. #define CX_PRIORITY         "CX_PRIORITY"
  156. #define DEF_CX_PRIORITY     0
  157. #define CX_POPKEY           "CX_POPKEY"
  158. #define DEF_CX_POPKEY       ""
  159. #define CX_POPUP            "CX_POPUP"
  160. #define DEF_CX_POPUP        NO
  161. #define DEF_TIMEOUT         3
  162. #define DEF_KEY             YES
  163.  
  164. #define POP_KEY_ID      100
  165.  
  166. #define CCMD_NOP                0
  167. #define CCMD_HIDE               1
  168. #define CCMD_QUIT               2
  169. #define CCMD_SECONDS            3
  170. #define CCMD_KEY                4
  171. #define CCMD_SECONDS_ACTIVATE   5
  172. #define CCMD_KEY_SHORTCUT       6
  173.  
  174. #define CASE_DIFF   ('A' - 'a')
  175.  
  176. /*
  177.  *  data for cback.o
  178.  */
  179. long _stack = 2048l;
  180. char *_procname = COM_NAME;
  181. long _priority = 0l;
  182. long _BackGroundIO = 1;
  183. extern BPTR _Backstdout;
  184.  
  185. /*
  186.  *  library base pointers
  187.  */
  188. struct IntuitionBase *IntuitionBase;
  189. struct Library *CxBase;
  190. struct Library *IconBase;
  191. struct Library *GadToolsBase;
  192. struct Library *GfxBase;
  193. struct Library *UtilityBase;
  194.  
  195. /*
  196.  *  our task
  197.  */
  198. struct Task *mytask = NULL;
  199.  
  200. /*
  201.  *  signal we AllocSignal() in main()
  202.  */
  203. long signal = -1l;
  204.  
  205. /*
  206.  *  message ports
  207.  */
  208. struct MsgPort *idcmpport   = NULL;
  209. struct MsgPort *cxport      = NULL;
  210.  
  211. /*
  212.  *  signal flags
  213.  */
  214. unsigned long customsigflag = 0l;
  215. unsigned long cxsigflag = 0l;
  216. unsigned long idcmpsigflag = 0l;
  217.  
  218. /*
  219.  *  programtitle and version for Version command
  220.  */
  221. char versionstring[] ="\0$VER: " COM_NAME " " VERSION;
  222.  
  223. /*
  224.  *  helpstring
  225.  */
  226. #ifdef GERMAN
  227. char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) von Stefan Sticht\n"\
  228.                     "Aufruf: " COM_NAME " [" CX_PRIORITY "=<n>] [" CX_POPKEY "=<hotkey>] ["
  229.                     CX_POPUP "=" YES "|" NO "] [" TT_TIMEOUT "=<Sekunden>] ["\
  230.                     TT_KEY "=" YES "|" NO "]\n";
  231. #else
  232. char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n"
  233.                     "Usage: " COM_NAME " [" CX_PRIORITY "=<n>] [" CX_POPKEY "=<hotkey>] ["
  234.                     CX_POPUP "=" YES "|" NO "] [" TT_TIMEOUT "=<seconds>] ["\
  235.                     TT_KEY "=" YES "|" NO "]\n";
  236. #endif
  237.  
  238. /*
  239.  *  timeout values
  240.  */
  241. unsigned short timeout;
  242. unsigned short timeoutseconds;
  243. unsigned short timeoutperiod;
  244. unsigned short keypress;
  245.  
  246. #define UNBLANKED   0
  247. #define BLANKED     1
  248. unsigned char blankstatus = UNBLANKED;
  249.  
  250. /*
  251.  *  the tooltypearray
  252.  */
  253. char **tooltypes;
  254.  
  255. /*
  256.  *  our broker
  257.  */
  258. CxObj *broker = NULL;
  259. CxObj *hotkeyfilter;
  260. CxObj *mousefilter;
  261. CxObj *timerfilter;
  262. CxObj *keyfilter;
  263.  
  264. struct NewBroker newbroker = {
  265.     NB_VERSION,                         /* BYTE nb_Version               */
  266.     COM_NAME,                           /* BYTE *nb_Name                 */
  267.     COM_TITLE,                          /* BYTE *nb_Title                */
  268.     COM_DESCR,                          /* BYTE *nb_Descr                */
  269.     NBU_NOTIFY | NBU_UNIQUE,            /* SHORT nb_Unique               */
  270.     COF_SHOW_HIDE,                      /* SHORT nb_Flags                */
  271.     0,                                  /* BYTE nb_Pri                   */
  272.     NULL,                               /* struct MsgPort nb_Port        */
  273.     0                                   /* WORD nb_ReservedChannel       */
  274. };
  275.  
  276. IX timerix = {
  277.     IX_VERSION,                         /* UBYTE ix_version     */
  278.     IECLASS_TIMER,                      /* UBYTE ix_Class       */
  279.     0,                                  /* UWORD ix_Code        */
  280.     0,                                  /* UWORD ix_CodeMask    */
  281.     0,                                  /* UWORD ix_Qualifier   */
  282.     0,                                  /* UWORD ix_Qualmask    */
  283.     0                                   /* UWORD ix_QualSame    */
  284.     };
  285.  
  286. IX mouseix = {
  287.     IX_VERSION,                         /* UBYTE ix_version     */
  288.     IECLASS_RAWMOUSE,                   /* UBYTE ix_Class       */
  289.     0,                                  /* UWORD ix_Code        */
  290.     0,                                  /* UWORD ix_CodeMask    */
  291.     IEQUALIFIER_RELATIVEMOUSE,          /* UWORD ix_Qualifier   */
  292.     IEQUALIFIER_RELATIVEMOUSE,          /* UWORD ix_Qualmask    */
  293.     0                                   /* UWORD ix_QualSame    */
  294.     };
  295.  
  296. IX keyix = {
  297.     IX_VERSION,                         /* UBYTE ix_version     */
  298.     IECLASS_RAWKEY,                     /* UBYTE ix_Class       */
  299.     0,                                  /* UWORD ix_Code        */
  300.     0,                                  /* UWORD ix_CodeMask    */
  301.     0,                                  /* UWORD ix_Qualifier   */
  302.     0,                                  /* UWORD ix_Qualmask    */
  303.     0                                   /* UWORD ix_QualSame    */
  304.     };
  305.  
  306. /*
  307.  *  data for our window
  308.  */
  309. struct Window *win          = NULL;
  310. APTR vi                     = NULL;
  311. struct Gadget *gadgetlist   = NULL;
  312. struct Screen *scr          = NULL;
  313. #define WINDOWTITLE_LEN 63
  314. char windowtitle[WINDOWTITLE_LEN + 1] = COM_TITLE;
  315.  
  316. /*
  317.  *  space for zoomed window pos & size
  318.  */
  319. WORD zoompos[4];
  320.  
  321. #define P_WA_Left       0
  322. #define P_WA_Top        1
  323. #define P_WA_Width      2
  324. #define P_WA_Height     3
  325. #define P_WA_Title      6
  326. #define P_WA_PubScreen  7
  327. #define P_WA_Gadgets    8
  328. struct TagItem mywindowtag[] = {
  329.     WA_Left,        0l,
  330.     WA_Top,         20l,
  331.     WA_Width,       400l,
  332.     WA_Height,      150l,
  333.     WA_IDCMP,       IDCMP_CLOSEWINDOW | BUTTONIDCMP | IDCMP_REFRESHWINDOW | IDCMP_VANILLAKEY,
  334.     WA_Flags,       WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
  335.                     WFLG_ACTIVATE | WFLG_RMBTRAP,
  336.     WA_Title,       (ULONG)windowtitle,
  337.     WA_PubScreen,   0l,
  338.     WA_Gadgets,     0l,
  339.     WA_Zoom,        (ULONG)zoompos,
  340.     TAG_END
  341.     };
  342.  
  343. char msg_seconds[] = MSG_SECONDS;
  344. char msg_key[]     = MSG_KEY;
  345. char msg_hide[]    = MSG_HIDE;
  346. char msg_quit[]    = MSG_QUIT;
  347.  
  348. /*
  349.  *  gadget definitions
  350.  */
  351. #define DBL_INTERWIDTH  (INTERWIDTH << 1)
  352. #define DBL_INTERHEIGHT (INTERHEIGHT << 1)
  353.  
  354. #define GAD_SECONDS 6
  355. #define GAD_KEY     7
  356. #define GAD_HIDE    8
  357. #define GAD_QUIT    9
  358.  
  359. struct Gadget *gad_seconds;
  360. struct Gadget *gad_key;
  361. struct Gadget *gad_hide;
  362. struct Gadget *gad_quit;
  363.  
  364. /********************************************************************
  365.  *                             functions                            *
  366.  ********************************************************************/
  367.  
  368. /*
  369.  *  request(): a glue routine to EasyRequest as simple as printf plus
  370.  *             titlestring, gadgettexts
  371.  *
  372.  *  Input: char *title:         pointer to the title of the requester
  373.  *         char *gadgets:       pointer to gadgettext
  374.  *         char *text:          text displayed in requester
  375.  *
  376.  *  Result: same as EasyrequestArgs()
  377.  *
  378.  * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!!
  379.  */
  380. long request(char *title, char *gadgets, char *text, ...)
  381. {
  382.     /*
  383.      *  structure textreq only needed in this function, so hide it here
  384.      *  must be static, in order to be initialized only once
  385.      */
  386.     static struct EasyStruct textreq = {
  387.         sizeof (struct EasyStruct), /* ULONG es_StructSize      */
  388.         0l,                         /* ULONG es_Flags           */
  389.         NULL,                       /* UBYTE *es_Title          */
  390.         NULL,                       /* UBYTE *es_TextFormat     */
  391.         NULL,                       /* UBYTE *es_GadgetFormat   */
  392.         };
  393.     va_list ap;
  394.     long rc;
  395.  
  396.     /*
  397.      *  get start of variable arguments
  398.      */
  399.     va_start(ap, text);
  400.  
  401.     /*
  402.      *  update textreq
  403.      */
  404.     textreq.es_Title = (UBYTE *)title;
  405.     textreq.es_TextFormat = (UBYTE *)text;
  406.     textreq.es_GadgetFormat = (UBYTE *)gadgets;
  407.  
  408.     /*
  409.      *  win may be NULL
  410.      */
  411.     rc = EasyRequestArgs(NULL, &textreq, NULL, ap);
  412.  
  413.     va_end(ap);
  414.  
  415.     return(rc);
  416. }
  417.  
  418. /*
  419.  *  myopenlibrary(): same as OpenLibrary(), but opens a retry-requester
  420.  *                   if OpenLibrary() fails, to give the user a chance to
  421.  *                   copy the library to libs: and retry
  422.  *                   requires request(), see above
  423.  */
  424. struct Library *myopenlibrary(char *name, unsigned long version)
  425. {
  426.     static char errortext[] = MSG_LIBRARY_OPENERR;
  427.     struct Library *libptr;
  428.     long ok = TRUE;
  429.  
  430.     do {
  431.         if (!(libptr = OpenLibrary((UBYTE *)name, version))) {
  432.             if (IntuitionBase) {
  433.                 ok = request(COM_NAME ":", RETRY_GADGETS, errortext, name, version);
  434.                 }
  435.             else ok = FALSE;
  436.             }
  437.         } while (!libptr && ok);
  438.  
  439.     #ifdef DEBUG
  440.     printf("myopenlibrary(%s, %ld) = 0x%lx\n", name, version, libptr);
  441.     #endif
  442.     return(libptr);
  443. }
  444.  
  445. void main(int argc, char *argv[])
  446. {
  447.     CxObj *customobj;
  448.     char *hotkey;
  449.     struct Message *msg;
  450.     long seconds;
  451.     short window = FALSE;
  452.  
  453.     if ((argc > 1) && (*argv[1] == '?')) {
  454.         /*
  455.          *  display help string
  456.          */
  457.         if (_Backstdout) {
  458.             Write(_Backstdout, helpstring, sizeof(helpstring) - 1l);
  459.             Close(_Backstdout);
  460.             }
  461.         return;
  462.         }
  463.     else if (argc && _Backstdout) Close(_Backstdout);
  464.  
  465.     if (IntuitionBase = (struct IntuitionBase *)myopenlibrary("intuition.library", 37l)) {
  466.  
  467.         /*
  468.          *  parse command line or tool types
  469.          *
  470.          *  we need icon.library therefore
  471.          */
  472.         if (IconBase = myopenlibrary("icon.library", 37l)) {
  473.  
  474.             /*
  475.              * create tooltypes array (requires icon.library open!!!)
  476.              */
  477.             tooltypes = (char **)ArgArrayInit(argc, argv);
  478.  
  479.             newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY);
  480.  
  481.             /*
  482.              *  check for a hotkey
  483.              */
  484.             hotkey = ArgString(tooltypes, CX_POPKEY, DEF_CX_POPKEY);
  485.  
  486.             /*
  487.              *  get the user's prefered timeout
  488.              */
  489.             seconds = ArgInt(tooltypes, TT_TIMEOUT, DEF_TIMEOUT);
  490.             if (seconds < 1) timeoutseconds = 0;
  491.             else timeoutseconds = seconds;
  492.             timeoutperiod = timeoutseconds * 10;
  493.  
  494.             if (UtilityBase = myopenlibrary("utility.library", 37l)) {
  495.  
  496.                 if (Stricmp(ArgString(tooltypes, CX_POPUP, DEF_CX_POPUP), YES) == 0l)
  497.                     window = TRUE;
  498.  
  499.                 /*
  500.                  *  blank on key press?
  501.                  */
  502.                 keypress = (Stricmp(ArgString(tooltypes, TT_KEY, DEF_KEY), YES) == 0l) ?
  503.                            TRUE : FALSE;
  504.  
  505.                 CloseLibrary(UtilityBase);
  506.  
  507.                 } /* if UtilityBase */
  508.  
  509.             if (CxBase = myopenlibrary("commodities.library", 37l)) {
  510.  
  511.                 if (GfxBase = myopenlibrary("graphics.library", 37l)) {
  512.  
  513.                     if (GadToolsBase = myopenlibrary("gadtools.library", 37l)) {
  514.  
  515.                         /*
  516.                          *  create our message port
  517.                          */
  518.                         if (cxport = CreateMsgPort()) {
  519.  
  520.                             cxsigflag = 1l << cxport->mp_SigBit;
  521.                             newbroker.nb_Port = cxport;
  522.  
  523.                             if (broker = CxBroker(&newbroker, NULL)) {
  524.  
  525.                                 if (timerfilter = CxFilter(NULL)) {
  526.  
  527.                                     AttachCxObj(broker, timerfilter);
  528.  
  529.                                     if (mousefilter = CxFilter(NULL)) {
  530.  
  531.                                         AttachCxObj(broker, mousefilter);
  532.  
  533.                                         if (keyfilter = CxFilter(NULL)) {
  534.  
  535.                                             AttachCxObj(broker, keyfilter);
  536.  
  537.                                             SetFilterIX(timerfilter, &timerix);
  538.                                             SetFilterIX(mousefilter, &mouseix);
  539.                                             SetFilterIX(keyfilter, &keyix);
  540.  
  541.                                             if ((signal = (long)AllocSignal(-1)) != -1) {
  542.  
  543.                                                 customsigflag = 1 << signal;
  544.  
  545.                                                 if (mytask = FindTask(NULL)) {
  546.  
  547.                                                     if (customobj = CxCustom(timermon, 0l)) {
  548.  
  549.                                                         AttachCxObj(timerfilter, customobj);
  550.  
  551.                                                         if (customobj = CxCustom(mousemon, 0l)) {
  552.  
  553.                                                             AttachCxObj(mousefilter, customobj);
  554.  
  555.                                                             if (customobj = CxCustom(keymon, 0l)) {
  556.  
  557.                                                                 AttachCxObj(keyfilter, customobj);
  558.  
  559.                                                                 if (*hotkey) {
  560.                                                                     unsigned long len;
  561.  
  562.                                                                     if (hotkeyfilter = HotKey(hotkey, cxport, POP_KEY_ID)) {
  563.                                                                         AttachCxObj(broker, hotkeyfilter);
  564.                                                                         len = strlen(windowtitle);
  565.                                                                         strncpy(windowtitle + len, ": HotKey=", WINDOWTITLE_LEN - len);
  566.                                                                         len += sizeof(": HotKey=") - 1;
  567.                                                                         strncpy(windowtitle + len, hotkey, WINDOWTITLE_LEN - len);
  568.                                                                         }
  569.  
  570.                                                                     } /* if hotkey */
  571.  
  572.                                                                 if (!CxObjError(timerfilter) &&
  573.                                                                     !CxObjError(mousefilter) &&
  574.                                                                     !CxObjError(keyfilter) &&
  575.                                                                     !(hotkeyfilter && CxObjError(hotkeyfilter))) {
  576.  
  577.                                                                     /*
  578.                                                                      *  deactivate timerfilter if timeout = 0
  579.                                                                      */
  580.                                                                     if (!timeoutseconds) ActivateCxObj(timerfilter, 0l);
  581.                                                                     /*
  582.                                                                      *  deactivate keyfilter if !keypress
  583.                                                                      */
  584.                                                                     if (!keypress) ActivateCxObj(keyfilter, 0l);
  585.                                                                     /*
  586.                                                                      *  activate our commodity
  587.                                                                      */
  588.                                                                     ActivateCxObj(broker, 1l);
  589.                                                                     /*
  590.                                                                      * deactivate again, if no timeout and not keypress
  591.                                                                      */
  592.                                                                     if (!timeoutseconds && !keypress) ActivateCxObj(broker, 0l);
  593.                                                                     /*
  594.                                                                      *  now watch our numerous ports
  595.                                                                      */
  596.                                                                     processmessages(window);
  597.  
  598.                                                                     } /* if !CxObjError() */
  599.  
  600.                                                                 } /* if keymon */
  601.  
  602.                                                             } /* if mousemon */
  603.  
  604.                                                         } /* if timermon */
  605.  
  606.                                                     } /* if mytask */
  607.  
  608.                                                 FreeSignal(signal);
  609.                                                 customsigflag = 0l;
  610.  
  611.                                                 } /* if signal */
  612.  
  613.                                             } /* if keyfilter */
  614.  
  615.                                         #ifdef DEBUG
  616.                                         else printf("main(): keyfilter = CxFilter() failed!\n");
  617.                                         #endif
  618.  
  619.                                         } /* if mousefilter */
  620.  
  621.                                     #ifdef DEBUG
  622.                                     else printf("main(): mousefilter = CxFilter() failed!\n");
  623.                                     #endif
  624.  
  625.                                     } /* if timerfilter */
  626.  
  627.                                 #ifdef DEBUG
  628.                                 else printf("main(): timerfilter = CxFilter() failed!\n");
  629.                                 #endif
  630.  
  631.                                 DeleteCxObjAll(broker);
  632.  
  633.                                 } /* if broker */
  634.  
  635.                             #ifdef DEBUG
  636.                             else printf("main(): CxBroker() failed!\n");
  637.                             #endif
  638.  
  639.                             /*
  640.                              *  delete our message port after replying all pending messages
  641.                              */
  642.                             while (msg = GetMsg(cxport)) ReplyMsg(msg);
  643.                             DeleteMsgPort(cxport);
  644.                             } /* if cxport */
  645.  
  646.                         #ifdef DEBUG
  647.                         else printf("main(): CraeteMsgPort() failed!\n");
  648.                         #endif
  649.  
  650.                         CloseLibrary(GadToolsBase);
  651.                         } /* if GadToolsBase */
  652.  
  653.                     CloseLibrary(GfxBase);
  654.                     } /* if GfxBase */
  655.  
  656.                 CloseLibrary(CxBase);
  657.                 } /* if CxBase */
  658.  
  659.             /*
  660.              *  free memory allocated by ArgArrayInit()
  661.              */
  662.             ArgArrayDone();
  663.  
  664.             CloseLibrary(IconBase);
  665.             } /* if IconBase */
  666.  
  667.         CloseLibrary((struct Library *)IntuitionBase);
  668.         } /* if IntuitionBase */
  669.  
  670. } /* main() */
  671.  
  672. void processmessages(short window)
  673. {
  674.     struct Message *msg;
  675.     unsigned long sigreceived;
  676.     unsigned long msgtype;
  677.     unsigned long msgid;
  678.     unsigned short quit = FALSE;
  679.     unsigned short windowopen = FALSE;
  680.     unsigned char command = CCMD_NOP;
  681.  
  682.     if (window) {
  683.         if (openwindow()) windowopen = TRUE;
  684.         }
  685.  
  686.     while (!quit) {
  687.  
  688.         sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag | customsigflag | idcmpsigflag);
  689.  
  690.         #ifdef DEBUG
  691.         printf("processmessages(): signal received\n");
  692.         #endif
  693.  
  694.         if (sigreceived & customsigflag) changestateofmousepointer(blankstatus);
  695.         if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE;
  696.  
  697.         if (sigreceived & cxsigflag) {
  698.  
  699.             #ifdef DEBUG
  700.             printf("processmessages(): message at cxport\n");
  701.             #endif
  702.  
  703.             while (msg = (struct Message *)GetMsg(cxport)) {
  704.  
  705.                 msgid = CxMsgID((CxMsg *)msg);
  706.                 msgtype = CxMsgType((CxMsg *)msg);
  707.  
  708.                 ReplyMsg(msg);
  709.  
  710.                 switch (msgtype) {
  711.  
  712.                     case CXM_IEVENT:
  713.                         if (msgid == POP_KEY_ID) {
  714.                             if (openwindow()) windowopen = TRUE;
  715.                             }
  716.                         break;
  717.  
  718.                     case CXM_COMMAND:
  719.                         switch (msgid) {
  720.  
  721.                             case CXCMD_KILL:
  722.                                 quit = TRUE;
  723.  
  724.                             case CXCMD_DISABLE:
  725.                                 ActivateCxObj(broker, 0l);
  726.                                 blankstatus = UNBLANKED;
  727.                                 changestateofmousepointer(blankstatus);
  728.                                 #ifdef DEBUG
  729.                                 printf("processmessages(): broker disabled\n");
  730.                                 #endif
  731.                                 break;
  732.  
  733.                             case CXCMD_ENABLE:
  734.                                 ActivateCxObj(broker, 1l);
  735.                                 #ifdef DEBUG
  736.                                 printf("processmessages(): broker enabled\n");
  737.                                 #endif
  738.                                 break;
  739.  
  740.                             case CXCMD_UNIQUE:
  741.                             case CXCMD_APPEAR:
  742.                                 if (openwindow()) windowopen = TRUE;
  743.                                 break;
  744.  
  745.                             case CXCMD_DISAPPEAR:
  746.                                 windowopen = FALSE;
  747.                                 closewindow();
  748.                                 break;
  749.  
  750.                             }
  751.                         break;
  752.  
  753.                     } /* switch msgtype */
  754.  
  755.                 } /* while CxMsg */
  756.  
  757.             } /* if (sigreceived & cxsigflag) */
  758.  
  759.         if (sigreceived & idcmpsigflag) {
  760.  
  761.             APTR *object;
  762.             ULONG class;
  763.             UWORD code;
  764.  
  765.             #ifdef DEBUG
  766.             printf("processmessages(): message at idcmpport\n");
  767.             #endif
  768.  
  769.             while (windowopen && (msg = (struct Message *)GT_GetIMsg(idcmpport))) {
  770.                 /*
  771.                  *  handle IDCMP messages
  772.                  */
  773.                 class    = ((struct IntuiMessage *)msg)->Class;
  774.                 code     = ((struct IntuiMessage *)msg)->Code;
  775.                 object   = ((struct IntuiMessage *)msg)->IAddress;
  776.                 GT_ReplyIMsg((struct IntuiMessage *)msg);
  777.  
  778.                 switch (class) {
  779.  
  780.                     case CLOSEWINDOW:
  781.                         command = CCMD_HIDE;
  782.                         break;
  783.  
  784.                     case REFRESHWINDOW:
  785.                         GT_BeginRefresh(win);
  786.                         GT_EndRefresh(win, TRUE);
  787.                         break;
  788.  
  789.                     case GADGETUP:
  790.                         if (object) command = (unsigned char)((struct Gadget *)object)->UserData;
  791.                         break;
  792.  
  793.                     case VANILLAKEY:
  794.                         switch (code) {
  795.  
  796.                             case 27:
  797.                             case MSG_HIDE_SCC:
  798.                             case MSG_HIDE_SCC - CASE_DIFF:
  799.                                         command = CCMD_HIDE;
  800.                                         break;
  801.  
  802.                             case MSG_QUIT_SCC:
  803.                             case MSG_QUIT_SCC - CASE_DIFF:
  804.                                         command = CCMD_QUIT;
  805.                                         break;
  806.  
  807.                             case MSG_SECONDS_SCC:
  808.                             case MSG_SECONDS_SCC - CASE_DIFF:
  809.                                         command = CCMD_SECONDS_ACTIVATE;
  810.                                         break;
  811.  
  812.                             case MSG_KEY_SCC:
  813.                             case MSG_KEY_SCC - CASE_DIFF:
  814.                                         command = CCMD_KEY_SHORTCUT;
  815.                                         break;
  816.  
  817.                             }
  818.                         break;
  819.  
  820.                     } /* switch class */
  821.  
  822.                 } /* while idcmp message */
  823.  
  824.             } /* if (sigreceived & idcmpsigflag) */
  825.  
  826.         #ifdef DEBUG
  827.         printf("processmessages(): command = %ld\n", command);
  828.         #endif
  829.  
  830.         switch(command) {
  831.  
  832.             case CCMD_NOP:
  833.                 break;
  834.  
  835.             case CCMD_HIDE:
  836.                 getseconds();
  837.                 closewindow();
  838.                 break;
  839.  
  840.             case CCMD_QUIT:
  841.                 quit = TRUE;
  842.                 break;
  843.  
  844.             case CCMD_SECONDS:
  845.                 getseconds();
  846.                 break;
  847.  
  848.             case CCMD_KEY_SHORTCUT:
  849.                 GT_SetGadgetAttrs(gad_key, win, NULL, GTCB_Checked, !keypress, TAG_END);
  850.  
  851.             case CCMD_KEY:
  852.                 keypress = !keypress;
  853.                 ActivateCxObj(keyfilter, keypress);
  854.                 #ifdef DEBUG
  855.                 printf("processmessages(): ActivateCxObj(keyfilter, %ld)\n", keypress);
  856.                 #endif
  857.                 if (!keypress && !timeoutseconds) {
  858.                     /*
  859.                      *  unblank mouse pointer
  860.                      */
  861.                     blankstatus = UNBLANKED;
  862.                     changestateofmousepointer(blankstatus);
  863.                     ActivateCxObj(broker, 0l);
  864.                     #ifdef DEBUG
  865.                     printf("processmessages(): broker disabled\n");
  866.                     #endif
  867.                     }
  868.                 else {
  869.                     ActivateCxObj(broker, 1l);
  870.                     #ifdef DEBUG
  871.                     printf("processmessages(): broker enabled\n");
  872.                     #endif
  873.                     }
  874.                 break;
  875.  
  876.             case CCMD_SECONDS_ACTIVATE:
  877.                 ActivateGadget(gad_seconds, win, NULL);
  878.                 break;
  879.  
  880.             } /* switch (command) */
  881.  
  882.         command = CCMD_NOP;
  883.  
  884.         } /* while !quit */
  885.  
  886.     ActivateCxObj(broker, 0l);
  887.     #ifdef DEBUG
  888.     printf("processmessages(): broker disabled\n");
  889.     #endif
  890.     changestateofmousepointer(UNBLANKED);
  891.     closewindow();
  892. }
  893.  
  894. /*
  895.  *  commodity functions
  896.  */
  897. void __saveds timermon(void)
  898. {
  899.     if (++timeout >= timeoutperiod) {
  900.         blankstatus = BLANKED;
  901.         if (mytask && customsigflag) Signal(mytask, customsigflag);
  902.         #ifdef DEBUG
  903.         printf(COM_NAME ": timermon blanked\n");
  904.         #endif
  905.         }
  906. }
  907.  
  908. void __saveds mousemon(void)
  909. {
  910.     #ifdef DEBUG
  911.     printf(COM_NAME ": mousemon\n");
  912.     #endif
  913.  
  914.     timeout = 0;
  915.     if (blankstatus == BLANKED) {
  916.         blankstatus = UNBLANKED;
  917.         if (mytask && customsigflag) Signal(mytask, customsigflag);
  918.         #ifdef DEBUG
  919.         printf(COM_NAME ": mousemon unblanked\n");
  920.         #endif
  921.         }
  922. }
  923.  
  924. void __saveds keymon(CxMsg *cxm)
  925. {
  926.     register struct InputEvent *ie = (struct InputEvent *)CxMsgData(cxm);
  927.  
  928.     #ifdef DEBUG
  929.     printf(COM_NAME ": keymon\n");
  930.     #endif
  931.  
  932.     if (ie->ie_Code < 0x60) {
  933.  
  934.         if (blankstatus == UNBLANKED) {
  935.             blankstatus = BLANKED;
  936.             if (mytask && customsigflag) Signal(mytask, customsigflag);
  937.             #ifdef DEBUG
  938.             printf(COM_NAME ": keymon blanked\n");
  939.             #endif
  940.             }
  941.  
  942.         }
  943.  
  944. }
  945.  
  946. void changestateofmousepointer(unsigned char blankstatus)
  947. {
  948.     if (blankstatus == BLANKED) {
  949.         /*
  950.          *  clear mouse pointer
  951.          */
  952.         WaitTOF();            
  953.         OFF_SPRITE;
  954.         custom.spr[0].dataa=0;
  955.         custom.spr[0].datab=0;
  956.         timeout = 0;
  957.  
  958.         if (keypress) {
  959.             /*
  960.              *  no mousepointer =>
  961.              *  disable keyfilter, no rawkey event needs to be monitored
  962.              *  if no timeout specified, enable mousefilter
  963.              */
  964.             if (!timeoutseconds) {
  965.                 ActivateCxObj(mousefilter, 1l);
  966.                 #ifdef DEBUG
  967.                 printf("changestateofmousepointer(): mousefilter enabled\n");
  968.                 #endif
  969.                 }
  970.             ActivateCxObj(keyfilter, 0l);
  971.             #ifdef DEBUG
  972.             printf("changestateofmousepointer(): keyfilter disabled\n");
  973.             #endif
  974.             }
  975.  
  976.         } /* if blanked */
  977.  
  978.     else {
  979.         ON_SPRITE;
  980.         timeout = 0;
  981.  
  982.         if (keypress) {
  983.             /*
  984.              *  mouse pointer on =>
  985.              *  enable keyfilter and disbale mousefilter if no timeout specified
  986.              */
  987.             if (!timeoutseconds) {
  988.                 ActivateCxObj(mousefilter, 0l);
  989.                 #ifdef DEBUG
  990.                 printf("changestateofmousepointer(): mousefilter disabled\n");
  991.                 #endif
  992.                 }
  993.             ActivateCxObj(keyfilter, 1l);
  994.             #ifdef DEBUG
  995.             printf("changestateofmousepointer(): keyfilter enabled\n");
  996.             #endif
  997.             }
  998.  
  999.         }
  1000. }
  1001.  
  1002. /*
  1003.  *  window functions
  1004.  */
  1005. long openwindow(void)
  1006. {
  1007.     struct DimensionInfo di;
  1008.     struct Rectangle *rect;
  1009.     unsigned long lock;
  1010.     unsigned long vpmid;
  1011.     long ok;
  1012.  
  1013.     if (win) {
  1014.         /*
  1015.          *  dont't open window but pop it to front, unzip it
  1016.          *
  1017.          *  unzip window if zipped
  1018.          */
  1019.         if (win->Height < mywindowtag[P_WA_Height].ti_Data) ZipWindow(win);
  1020.  
  1021.         /*
  1022.          *  window to front
  1023.          */
  1024.         WindowToFront(win);
  1025.  
  1026.         /*
  1027.          *  activate window
  1028.          */
  1029.         lock = LockIBase(0l);
  1030.         if (win != IntuitionBase->ActiveWindow) {
  1031.             UnlockIBase(lock);
  1032.             ActivateWindow(win);
  1033.             }
  1034.         else UnlockIBase(lock);
  1035.  
  1036.         /*
  1037.          *  screen to front
  1038.          */
  1039.         lock = LockIBase(0l);
  1040.         if (win->WScreen != IntuitionBase->FirstScreen) {
  1041.             UnlockIBase(lock);
  1042.             ScreenToFront(win->WScreen);
  1043.             }
  1044.         else UnlockIBase(lock);
  1045.  
  1046.         ok = TRUE;
  1047.  
  1048.         }
  1049.  
  1050.     else {
  1051.         /*
  1052.          *  lock the default public screen
  1053.          */
  1054.         if (scr = LockPubScreen(NULL)) {
  1055.             /*
  1056.              *  GetVisualInfo() for gadtools
  1057.              */
  1058.             if (vi = GetVisualInfo(scr, TAG_DONE)) {
  1059.                 /*
  1060.                  *  update some window information
  1061.                  */
  1062.                 mywindowtag[P_WA_Width].ti_Data = zoompos[2] =
  1063.                     TextLength(&scr->RastPort, (STRPTR)windowtitle, strlen(windowtitle)) + 100;
  1064.                 mywindowtag[P_WA_Height].ti_Data = zoompos[3] =
  1065.                     scr->WBorTop + scr->RastPort.TxHeight + 1;
  1066.                 /*
  1067.                  *  create all gadgets:
  1068.                  *
  1069.                  *  this function may also change the width and height of our window
  1070.                  */
  1071.                 if (createallgadgets(&gadgetlist, vi, scr,
  1072.                                      &mywindowtag[P_WA_Height].ti_Data,
  1073.                                      &mywindowtag[P_WA_Width].ti_Data)) {
  1074.                     /*
  1075.                      *  center the window in the visible box of the screen
  1076.                      */
  1077.                     if ((vpmid = GetVPModeID(&scr->ViewPort )) != INVALID_ID) {
  1078.  
  1079.                         GetDisplayInfoData(0, (UBYTE *)&di, sizeof(struct DimensionInfo), DTAG_DIMS, vpmid);
  1080.                         rect = &di.TxtOScan;
  1081.                         zoompos[0] = mywindowtag[P_WA_Left].ti_Data =
  1082.                             (scr->LeftEdge < 0 ? -scr->LeftEdge : 0) +
  1083.                             ((min((rect->MaxX - rect->MinX + 1), scr->Width) -
  1084.                               mywindowtag[P_WA_Width].ti_Data) >> 1);
  1085.                         zoompos[1] = mywindowtag[P_WA_Top].ti_Data =
  1086.                             (scr->TopEdge < 0 ? -scr->TopEdge : 0) +
  1087.                             ((min((rect->MaxY - rect->MinY + 1), scr->Height) -
  1088.                               mywindowtag[P_WA_Height].ti_Data) >> 1);
  1089.  
  1090.                         }
  1091.  
  1092.                     mywindowtag[P_WA_PubScreen].ti_Data = (ULONG)scr;
  1093.  
  1094.                     mywindowtag[P_WA_Gadgets].ti_Data = (ULONG)gadgetlist;
  1095.                     if (win = OpenWindowTagList(NULL, mywindowtag)) {
  1096.                         /*
  1097.                          *  save IDCMP port
  1098.                          */
  1099.                         idcmpport = win->UserPort;
  1100.                         idcmpsigflag = 1L << idcmpport->mp_SigBit;
  1101.                 
  1102.                         GT_RefreshWindow(win, NULL);
  1103.                 
  1104.                         /*
  1105.                          *  switch screen to front
  1106.                          */
  1107.                         lock = LockIBase(0l);
  1108.                         if (win->WScreen != IntuitionBase->FirstScreen) {
  1109.                             UnlockIBase(lock);
  1110.                             ScreenToFront(win->WScreen);
  1111.                             }
  1112.                         else UnlockIBase(lock);
  1113.  
  1114.                         ok = TRUE;
  1115.  
  1116.                         } /* if (win = OpenWindowTagList(NULL, mywindowtag)) */
  1117.  
  1118.                     } /* if (createallgadgets() */
  1119.  
  1120.                 } /*  if (vi = GetVisualInfo(scr, TAG_DONE)) */
  1121.  
  1122.             } /* if (scr = LockPubScreen(NULL)) */
  1123.  
  1124.         if (!ok) {
  1125.                 /*
  1126.                  *  window could not be opened - free all resources
  1127.                  */
  1128.                 closewindow();
  1129.                 }
  1130.  
  1131.         } /* if (!win) */
  1132.         
  1133.     return(ok);
  1134. }
  1135.  
  1136. void closewindow(void)
  1137. {
  1138.  
  1139.     if (win) {
  1140.         CloseWindow(win);
  1141.         win = NULL;
  1142.         idcmpport = NULL;
  1143.         idcmpsigflag = 0l;
  1144.         }
  1145.  
  1146.     if (gadgetlist) {
  1147.         FreeGadgets(gadgetlist);
  1148.         gadgetlist = NULL;
  1149.         }
  1150.  
  1151.     if (vi) {
  1152.         FreeVisualInfo(vi);
  1153.         vi = NULL;
  1154.         }
  1155.  
  1156.     if (scr) {
  1157.         UnlockPubScreen(NULL, scr);
  1158.         scr = NULL;
  1159.         }
  1160. }
  1161.  
  1162. void getseconds(void)
  1163. {
  1164.     long seconds;
  1165.  
  1166.     if (blankstatus == BLANKED && !keypress) {
  1167.         /*
  1168.          *  unblank mouse pointer
  1169.          */
  1170.         blankstatus = UNBLANKED;
  1171.         changestateofmousepointer(blankstatus);
  1172.         }
  1173.  
  1174.     if ((seconds = ((struct StringInfo *)gad_seconds->SpecialInfo)->LongInt) > 0) {
  1175.         /*
  1176.          *  input value ok
  1177.          */
  1178.         timeoutseconds = seconds;
  1179.         timeoutperiod  = timeoutseconds * 10;
  1180.         timeout = 0;
  1181.  
  1182.         ActivateCxObj(timerfilter, 1l);
  1183.         #ifdef DEBUG
  1184.         printf("getseconds(): timerfilter enabled\n");
  1185.         #endif
  1186.  
  1187.         ActivateCxObj(broker, 1l);
  1188.         #ifdef DEBUG
  1189.         printf("getseconds(): broker enabled\n");
  1190.         #endif
  1191.         }
  1192.  
  1193.     else {
  1194.         /*
  1195.          *  value given was < 1
  1196.          */
  1197.         timeoutseconds = timeout = 0;
  1198.  
  1199.         /*
  1200.          *  disable timerfilter
  1201.          */
  1202.         ActivateCxObj(timerfilter, 0l);
  1203.  
  1204.         /*
  1205.          *  update gadget contents
  1206.          */
  1207.         GT_SetGadgetAttrs(gad_seconds, win, NULL, GTIN_Number, timeoutseconds, TAG_END);
  1208.  
  1209.         }
  1210.  
  1211.     /*
  1212.      *  disable broker if all blanking actions are disabled
  1213.      */
  1214.     if (!keypress && !timeoutseconds) {
  1215.         ActivateCxObj(broker, 0l);
  1216.         #ifdef DEBUG
  1217.         printf("getseconds(): broker disabled\n");
  1218.         #endif
  1219.         }
  1220. }
  1221.  
  1222. /*
  1223.  *  createallgadgets(): create all gadgets and put required width and height
  1224.  *                      of window in height and width
  1225.  */
  1226. struct Gadget *
  1227. createallgadgets(struct Gadget **glist, APTR vi, struct Screen *scr, ULONG *height, ULONG *width)
  1228. {
  1229.     static struct NewGadget ng;
  1230.     struct Gadget *gad;
  1231.     struct RastPort *rp;
  1232.     short buttonwidth;
  1233.     short keywidth;
  1234.     short secondswidth;
  1235.     short dummy;
  1236.  
  1237.     /*
  1238.      *  first get RastPort of screen to determine some TextLength()
  1239.      */
  1240.     rp = &scr->RastPort;
  1241.  
  1242.     /*
  1243.      *  calculate width of the seconds gadget:
  1244.      *      I tried out that 8 times the width of the digit "0" gives a nice value
  1245.      *      for the integer gadget; add INTERWIDTH and length of gadgettitle
  1246.      */    
  1247.     secondswidth = ((TextLength(rp, (STRPTR)"0", 1l)) << 3) + INTERWIDTH +
  1248.                    TextLength(rp, (STRPTR)&msg_seconds[1], strlen(msg_seconds) - 1l);
  1249.  
  1250.     *width = max(secondswidth + DBL_INTERWIDTH, *width);
  1251.  
  1252.     /*
  1253.      *
  1254.      */
  1255.     keywidth = TextLength(rp, (STRPTR)msg_key, strlen(msg_key)) -
  1256.                TextLength(rp, (STRPTR)"_", 1l) + 26 + INTERWIDTH;
  1257.     *width = max(keywidth + DBL_INTERWIDTH, *width);
  1258.  
  1259.     buttonwidth = TextLength(rp, (STRPTR)&msg_hide[1], strlen(msg_hide) - 1l);
  1260.     dummy       = TextLength(rp, (STRPTR)&msg_quit[1], strlen(msg_quit) - 1l);
  1261.     buttonwidth = max(buttonwidth, dummy);
  1262.     buttonwidth += DBL_INTERWIDTH;
  1263.     /*
  1264.      *  check out if the window's width has to be enlarged
  1265.      */
  1266.     *width = max((buttonwidth << 1) + (DBL_INTERWIDTH + INTERWIDTH), *width);
  1267.  
  1268.     /*
  1269.      *  now create the gadgets
  1270.      */
  1271.     gad = CreateContext(glist);
  1272.  
  1273.     /*
  1274.      *  seconds gadget
  1275.      */
  1276.     ng.ng_TopEdge = scr->WBorTop + rp->TxHeight + 1 + DBL_INTERHEIGHT;
  1277.     ng.ng_Width   = (TextLength(rp, (STRPTR)"0", 1l)) << 3;
  1278.     ng.ng_LeftEdge = TextLength(rp, (STRPTR)&msg_seconds[1], strlen(msg_seconds) - 1l);
  1279.     ng.ng_LeftEdge += (*width - secondswidth) >> 1;
  1280.  
  1281.     ng.ng_Height        = rp->TxHeight + 4;
  1282.     ng.ng_GadgetText    = (UBYTE *)msg_seconds;
  1283.     ng.ng_TextAttr      = scr->Font;
  1284.     ng.ng_GadgetID      = GAD_SECONDS;
  1285.     ng.ng_Flags         = PLACETEXT_LEFT;
  1286.     ng.ng_VisualInfo    = vi;
  1287.     ng.ng_UserData      = (APTR)CCMD_SECONDS;
  1288.  
  1289.     gad_seconds = gad = CreateGadget(INTEGER_KIND, gad, &ng,
  1290.                                     GTIN_MaxChars, 3l,
  1291.                                     GTIN_Number, (ULONG)timeoutseconds,
  1292.                                     GT_Underscore, '_',
  1293.                                     TAG_DONE);
  1294.  
  1295.     /*
  1296.      *  key pressed gadget
  1297.      */
  1298.     ng.ng_TopEdge  += ng.ng_Height + INTERHEIGHT;
  1299.     ng.ng_LeftEdge  = (*width - keywidth) >> 1;
  1300.     ng.ng_GadgetText    = (UBYTE *)msg_key;
  1301.     ng.ng_GadgetID      = GAD_KEY;
  1302.     ng.ng_Flags         = PLACETEXT_RIGHT;
  1303.     ng.ng_UserData      = (APTR)CCMD_KEY;
  1304.  
  1305.     gad_key = gad = CreateGadget(CHECKBOX_KIND, gad, &ng, GTCB_Checked, keypress,
  1306.                                                           GT_Underscore, '_',
  1307.                                                           TAG_DONE);
  1308.  
  1309.     /*
  1310.      *  dummy now gets the spacing between the button gadgets
  1311.      */
  1312.     dummy = (*width - (buttonwidth << 1)) / 3;
  1313.  
  1314.     /*
  1315.      *  Hide gadget
  1316.      */    
  1317.     ng.ng_TopEdge      += ng.ng_Height + INTERHEIGHT;
  1318.     ng.ng_Width         = buttonwidth;
  1319.     ng.ng_LeftEdge      = dummy;
  1320.     ng.ng_GadgetText    = (UBYTE *)msg_hide;
  1321.     ng.ng_GadgetID      = GAD_HIDE;
  1322.     ng.ng_Flags         = 0l;
  1323.     ng.ng_UserData      = (APTR)CCMD_HIDE;
  1324.  
  1325.     gad_hide = gad = CreateGadget(BUTTON_KIND, gad, &ng, GT_Underscore, '_', TAG_DONE);
  1326.  
  1327.     /*
  1328.      *  Quit gadget
  1329.      */    
  1330.     ng.ng_LeftEdge     += ng.ng_Width + dummy;
  1331.     ng.ng_GadgetText    = (UBYTE *)msg_quit;
  1332.     ng.ng_GadgetID      = GAD_QUIT;
  1333.     ng.ng_UserData      = (APTR)CCMD_QUIT;
  1334.  
  1335.     gad_quit = gad = CreateGadget(BUTTON_KIND, gad, &ng, GT_Underscore, '_', TAG_DONE);
  1336.  
  1337.     *height = gad->TopEdge + gad->Height + DBL_INTERHEIGHT;
  1338.  
  1339.     return(gad);
  1340. }
  1341.